package org.infodavid.common.ejb;

import java.util.HashMap;
import java.util.Map;

import javax.ejb.Local;
import javax.ejb.PrePassivate;
import javax.ejb.Remote;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;

import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.annotations.OptimisticLockType;
import org.hibernate.annotations.Persister;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;

import org.infodavid.common.impl.model.AbstractCategory;
import org.infodavid.common.model.ITemplateCategory;
import org.infodavid.common.model.impl.persisters.VersionSafeSingleTableEntityPersister;
import org.infodavid.common.persistence.TemplateCategoryDataService;

/**
 * The Class TemplateCategoryBean.
 */
@Entity(name = "ITemplateCategory")
@org.hibernate.annotations.Entity(dynamicUpdate = true, selectBeforeUpdate = true, dynamicInsert = true, optimisticLock = OptimisticLockType.VERSION)
@Persister(impl = VersionSafeSingleTableEntityPersister.class)
@Table(name = "TEMPLATE_CATEGORIES")
@NamedQueries(value = {
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_COUNT, query = "select count(d."
        + ITemplateCategory.KEY + ") from ITemplateCategory d"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND, query = "select d from ITemplateCategory d"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_ACTIVE_COUNT, query = "select count(d."
        + ITemplateCategory.KEY + ") from ITemplateCategory d where d.archived = 0"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_ACTIVE, query = "select d from ITemplateCategory d where d.archived = 0"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_BY_NAME, query = "select d from ITemplateCategory d where d.archived = 0 and :"
        + ITemplateCategory.NAME
        + " is not null and d."
        + ITemplateCategory.NAME
        + " = :"
        + ITemplateCategory.NAME),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_BY_CREATION_DATE, query = "select d from ITemplateCategory d where d.archived = 0 and d."
        + ITemplateCategory.CREATION_DATE + " between :date1 and :date2"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_BY_CREATION_DATE_COUNT, query = "select count(d."
        + ITemplateCategory.KEY
        + ") from ITemplateCategory d where d.archived = 0 and d."
        + ITemplateCategory.CREATION_DATE + " between :date1 and :date2"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_BY_MODIFICATION_DATE, query = "select d from ITemplateCategory d where d.archived = 0 and d."
        + ITemplateCategory.MODIFICATION_DATE + " between :date1 and :date2"),
    @NamedQuery(name = TemplateCategoryDataService.QUERY_FIND_BY_MODIFICATION_DATE_COUNT, query = "select count(d."
        + ITemplateCategory.KEY
        + ") from ITemplateCategory d where d.archived = 0 and d."
        + ITemplateCategory.MODIFICATION_DATE + " between :date1 and :date2")
})
@Local(value = ITemplateCategory.class)
@Remote(value = ITemplateCategoryRemote.class)
public class TemplateCategoryBean extends AbstractCategory<ITemplateCategory> implements
    ITemplateCategory {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1660345027625851668L;

	/**
	 * The Constructor.
	 * @throws Exception the exception
	 */
	protected TemplateCategoryBean() throws Exception {
		super();
	}

	/**
	 * The Constructor.
	 * @param keyArg the key arg
	 * @throws Exception the exception
	 */
	protected TemplateCategoryBean(final Long keyArg) throws Exception {
		super(keyArg);
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.AbstractCategory#init()
	 */
	@Override
	@PrePassivate
	public void init() throws Exception {
		super.init();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#getCreationDate()
	 */
	@Override
	@Column(name = CREATION_DATE, nullable = false, updatable = false)
	@Type(type = "org.infodavid.persistence.impl.hibernate.usertype.DateTimeUserType")
	@Index(name = "IDX_TEMPLATE_CATEGORIES_CREATIONDATE")
	public DateTime getCreationDate() {
		return super.getCreationDate();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#getModificationDate()
	 */
	@Override
	@Version
	@Column(name = MODIFICATION_DATE, nullable = false)
	@Type(type = "org.infodavid.persistence.impl.hibernate.usertype.DateTimeUserType")
	public DateTime getModificationDate() {
		return super.getModificationDate();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#getKey()
	 */
	@Override
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = ID, nullable = false)
	public Long getKey() {
		return super.getKey();
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.impl.model.DataObjectImpl#isArchived()
	 */
	@Override
	@Column(name = ARCHIVED, nullable = false)
	@Index(name = "IDX_TEMPLATE_CATEGORIES_ARCHIVED")
	public boolean isArchived() {
		return super.isArchived();
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.impl.model.AbstractCategory#getName()
	 */
	@Override
	@Column(name = NAME, length = 128, nullable = false, updatable = true)
	@Index(name = "IDX_TEMPLATE_CATEGORIES_NAME")
	public String getName() {
		return super.getName();
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.impl.model.AbstractCategory#getComment()
	 */
	@Override
	@Column(name = COMMENT, length = 1024, nullable = true)
	public String getComment() {
		return super.getComment();
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.impl.model.AbstractCategory#getSubCategories()
	 */
	@Override
	@OneToMany(mappedBy = PARENT, targetEntity = TemplateCategoryBean.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@javax.persistence.MapKey(name = NAME)
	@OnDelete(action = OnDeleteAction.CASCADE)
	@ForeignKey(name = "FK_TEMPLATE_CATEGORIES_CHILDREN")
	@Target(value=HashMap.class)
	public Map<String,ITemplateCategory> getSubCategories() {
		return super.getSubCategories();
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.impl.model.AbstractCategory#getParent()
	 */
	@Override
	@JoinColumn(name = PARENT, referencedColumnName = ID, nullable = true)
	@ManyToOne(targetEntity = TemplateCategoryBean.class, fetch = FetchType.LAZY)
	@OnDelete(action = OnDeleteAction.CASCADE)
	@ForeignKey(name = "FK_TEMPLATE_CATEGORIES_PARENT")
	public ITemplateCategory getParent() {
		return super.getParent();
	}
}
